﻿using Edutainment.Interfaces;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Resources;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Edutainment
{
    /// <summary>
    /// Interaktionslogik für BUbbleSortExerciseWindow.xaml
    /// </summary>
    public partial class BubbleSortExerciseWindow : UserControl, ISortationInterface
    {

        public ArrayList buttonList { get; set; }
        ArrayList clickedButtons;
        ArrayList wrongClickedButtons;

        ButtonController bController;
        SortationController sController;
        BubbleSort current;

        Rectangle tipRectangle;

        public BubbleSortExerciseWindow()
        {
            InitializeComponent();
            App currentApp = (App)Application.Current;

            bController = currentApp.getAppManager().buttonController;
            sController = currentApp.getAppManager().sortController;

            clickedButtons = new ArrayList();
            wrongClickedButtons = new ArrayList();
            current = sController.bubbleSort;

        }

        public void setDelegate()
        {
            if (current != null)
            {
                current.sortationDelegate = this;
            }
        }

        private void initNewButtons()
        {
            if (current != null)
                current.sortationDelegate = null;
            sController.prepareBubbleSort(8, true);
            current = (BubbleSort)sController.currentSortAlgorithm;
            current.restart();
            bController.createButtonsWithList(sController.currentSortAlgorithm.getListToSort());

            buttonList = bController.buttons;
            current.sortationDelegate = this;
        }

        public void removeButtons()
        {
            clickedButtons.Clear();
            wrongClickedButtons.Clear();

            if (buttonList != null)
                buttonList.Clear();
            ButtonPositionCanvas.Children.Clear();
        }

        public void showButtons(bool animated)
        {
            removeButtons();
            initNewButtons();

            if (buttonList != null && buttonList.Count > 0)
            {
                int buttonWidth = 80;
                int buttonMargin = 10;
                Canvas toUse = ButtonPositionCanvas;
                toUse.VerticalAlignment = VerticalAlignment.Center;
                double gridWidth = toUse.Width;

                int bCounter = 1;
                DoubleAnimationUsingKeyFrames animate = null;


                foreach (ToggleButton button in buttonList)
                {
                    Thickness bThickness = new Thickness((bCounter * buttonMargin) + ((bCounter - 1) * buttonWidth), 20, bCounter * buttonMargin, 0);
                    button.Margin = bThickness;
                    button.Width = buttonWidth;
                    button.Height = 100;
                    button.Visibility = Visibility.Visible;
                    button.Style = (Style)FindResource("InformButton");
                    button.Click += onToggleButtonClicked;
                    
                    toUse.Children.Add(button);


                    if (animated)
                    {
                        button.Opacity = 0.0;
                        double kfDuration = (double)bCounter / 2.0;
                        double test = ((double)kfDuration) - .5;

                        animate = new DoubleAnimationUsingKeyFrames();
                        animate.Duration = TimeSpan.FromSeconds(kfDuration);
                        LinearDoubleKeyFrame dkf1 = new LinearDoubleKeyFrame(0.0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(test)));
                        LinearDoubleKeyFrame dkf2 = new LinearDoubleKeyFrame(1.0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(kfDuration)));

                        animate.KeyFrames.Add(dkf1);
                        animate.KeyFrames.Add(dkf2);

                        button.BeginAnimation(ToggleButton.OpacityProperty, animate);
                    }
                    bCounter++;

                }
            }
            current.start();
        }

        private void animateButtonSwap(int a, int b)
        {
            if (a >= 0 && a < buttonList.Count && b >= 0 && b < buttonList.Count)
            {
                ToggleButton buttonA = (ToggleButton)buttonList[a];
                ToggleButton buttonB = (ToggleButton)buttonList[b];

                Thickness thickA = buttonA.Margin;
                Thickness thickB = buttonB.Margin;

                Duration dur = new Duration(TimeSpan.FromSeconds(0.5));

                PowerEase pEase = new PowerEase();
                pEase.EasingMode = EasingMode.EaseInOut;

                ThicknessAnimation thickAnim1 = new ThicknessAnimation(thickB, dur);
                ThicknessAnimation thickAnim2 = new ThicknessAnimation(thickA, dur);
                thickAnim1.EasingFunction = pEase;
                thickAnim2.EasingFunction = pEase;

                Storyboard.SetTarget(thickAnim1, buttonA);
                Storyboard.SetTarget(thickAnim2, buttonB);
                Storyboard.SetTargetProperty(thickAnim1, new PropertyPath(ToggleButton.MarginProperty));
                Storyboard.SetTargetProperty(thickAnim2, new PropertyPath(ToggleButton.MarginProperty));

                Storyboard sbThickness = new Storyboard();
                sbThickness.Children.Add(thickAnim1);
                sbThickness.Children.Add(thickAnim2);

                sbThickness.Completed += swapAnimationCompleted;
                sbThickness.Begin();


            }

        }

        private void animateIncorrectSwap(int a, int b)
        {
            if (a >= 0 && a < buttonList.Count && b >= 0 && b < buttonList.Count)
            {
                ToggleButton buttonA = (ToggleButton)buttonList[a];
                ToggleButton buttonB = (ToggleButton)buttonList[b];



                buttonA.RenderTransform = new RotateTransform();
                buttonB.RenderTransform = new RotateTransform();
                buttonA.RenderTransformOrigin = new Point(0.5, 0.5);
                buttonB.RenderTransformOrigin = new Point(0.5, 0.5);

                Duration dur = new Duration(TimeSpan.FromSeconds(0.2));

                DoubleAnimationUsingKeyFrames doubleAnimKeyFrame = new DoubleAnimationUsingKeyFrames();

                LinearDoubleKeyFrame lDKF1 = new LinearDoubleKeyFrame(-5, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.05)));
                LinearDoubleKeyFrame lDKF2 = new LinearDoubleKeyFrame(5, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.1)));
                LinearDoubleKeyFrame lDKF3 = new LinearDoubleKeyFrame(-5, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.15)));
                LinearDoubleKeyFrame lDKF4 = new LinearDoubleKeyFrame(0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.20)));

                doubleAnimKeyFrame.KeyFrames.Add(lDKF1);
                doubleAnimKeyFrame.KeyFrames.Add(lDKF2);
                doubleAnimKeyFrame.KeyFrames.Add(lDKF3);
                doubleAnimKeyFrame.KeyFrames.Add(lDKF4);

                DoubleAnimationUsingKeyFrames doubleAnimeKeyFrameClone = doubleAnimKeyFrame.Clone();

                Storyboard.SetTarget(doubleAnimKeyFrame, buttonA);
                Storyboard.SetTargetProperty(doubleAnimKeyFrame, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
                Storyboard.SetTarget(doubleAnimeKeyFrameClone, buttonB);
                Storyboard.SetTargetProperty(doubleAnimeKeyFrameClone, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));

                Storyboard sb = new Storyboard();
                sb.Children.Add(doubleAnimKeyFrame);
                sb.Children.Add(doubleAnimeKeyFrameClone);

                sb.Begin();


                /*DoubleAnimation rotateAnimationA = new DoubleAnimation();
                rotateAnimationA.From = 0;
                rotateAnimationA.To = 10;
                rotateAnimationA.Duration = dur;

                DoubleAnimation rotateAnimationB = new DoubleAnimation();
                rotateAnimationB.From = 0;
                rotateAnimationB.To = 10;
                rotateAnimationB.Duration = dur;

                Storyboard.SetTarget(rotateAnimationA, buttonA);
                Storyboard.SetTarget(rotateAnimationB, buttonB);
                Storyboard.SetTargetProperty(rotateAnimationA, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
                Storyboard.SetTargetProperty(rotateAnimationB, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
                

                Storyboard sbRotation = new Storyboard();
                sbRotation.AutoReverse = true;
                sbRotation.Children.Add(rotateAnimationA);
                sbRotation.Children.Add(rotateAnimationB);

                sbRotation.Begin();*/
            }
        }

        private void animateButtonSelection(ToggleButton a, ToggleButton b, bool correct)
        {
            ToggleButton buttonA = a;
            ToggleButton buttonB = b;

            wrongClickedButtons.Add(buttonA);
            wrongClickedButtons.Add(buttonB);

            Duration dur = new Duration(TimeSpan.FromSeconds(1));

            SolidColorBrush selectCBrush;
            if (!correct)
                selectCBrush = (SolidColorBrush)FindResource("WrongSelectionBrush");
            else
                selectCBrush = (SolidColorBrush)FindResource("NormalBrush");

            ColorAnimation wrongSelectionAnimationB1 = new ColorAnimation();
            wrongSelectionAnimationB1.To = selectCBrush.Color;
            wrongSelectionAnimationB1.Duration = dur;
            ColorAnimation wrongSelectionAnimationB2 = wrongSelectionAnimationB1.Clone();

            Storyboard.SetTarget(wrongSelectionAnimationB1, buttonA);
            Storyboard.SetTarget(wrongSelectionAnimationB2, buttonB);
            //Storyboard.SetTargetProperty(wrongSelectionAnimationB1, new PropertyPath("(ToggleButton.Background).(RadialGradientBrush.GradientStops)[1].(GradientStop.Color)"));
            Storyboard.SetTargetProperty(wrongSelectionAnimationB1, new PropertyPath("(ToggleButton.Background).(SolidColorBrush.Color)"));
            Storyboard.SetTargetProperty(wrongSelectionAnimationB2, new PropertyPath("(ToggleButton.Background).(SolidColorBrush.Color)"));

            Storyboard sb = new Storyboard();
            sb.Children.Add(wrongSelectionAnimationB1);
            sb.Children.Add(wrongSelectionAnimationB2);

            sb.Begin();
        }

        private void swapAnimationCompleted(object sender, EventArgs e)
        {
            if (clickedButtons.Count > 0)
            {
                ToggleButton button1 = clickedButtons[0] as ToggleButton;
                ToggleButton button2 = clickedButtons[1] as ToggleButton;

                button2.IsChecked = false;
                button1.IsChecked = false;

                clickedButtons.Clear();
            }
        }

        public void onToggleButtonClicked(object sender, RoutedEventArgs e)
        {
            ToggleButton pressedButton = sender as ToggleButton;

            if (wrongClickedButtons.Contains(pressedButton))
            {
                this.animateButtonSelection((ToggleButton)wrongClickedButtons[0], (ToggleButton)wrongClickedButtons[1], true);
                wrongClickedButtons.Clear();
            }

            MediaPlayer mp = new MediaPlayer();
           
        if (clickedButtons.Contains(pressedButton))
            {
                clickedButtons.Remove(pressedButton);
            }
            else
            {
                if (clickedButtons.Count < 2)
                {
                    clickedButtons.Add(pressedButton);
                    if (clickedButtons.Count == 2)
                    {

                        int indxA = buttonList.IndexOf(clickedButtons[1]);
                        int indxB = buttonList.IndexOf(clickedButtons[0]);
                        if (indxA < indxB - 1 || indxA > indxB + 1)
                        {
                            //this.animateButtonSelection((ToggleButton)clickedButtons[1], (ToggleButton)clickedButtons[0], false);
                            this.animateIncorrectSwap(indxA, indxB);
                        }
                        else
                        {
                            bool correct = current.correctStep(indxA, indxB);
                            if (correct)
                            {
                                mp.Open(new Uri(@"sounds\field_swap.wav", UriKind.RelativeOrAbsolute));
                                mp.Play();

                                current.swap(buttonList, indxA, indxB);
                                this.animateButtonSwap(indxA, indxB);
                            }
                            else
                            {
                                mp.Open(new Uri(@"sounds\field_incorrect.wav", UriKind.RelativeOrAbsolute));
                                mp.Play();

                                this.animateIncorrectSwap(indxA, indxB);
                            }
                        }
                    }
                    else
                    {
                        mp.Open(new Uri(@"sounds\field_click.wav", UriKind.RelativeOrAbsolute));
                        mp.Play();

                    }

                }
                else
                {
                    pressedButton.IsChecked = !pressedButton.IsChecked;
                }
            }
        }

        private void tipButtonClicked(Object sender, RoutedEventArgs e)
        {
            Tuple<int, int> nxtStep = current.getNextStep();
            if (nxtStep != null && !ButtonPositionCanvas.Children.Contains(tipRectangle))
            {
                ToggleButton a = (ToggleButton)buttonList[(int)nxtStep.Item1];
                ToggleButton b = (ToggleButton)buttonList[(int)nxtStep.Item2];

                Thickness aThick = a.Margin;
                Thickness bThick = b.Margin;

                double width = b.Width + a.Width + 10.0 + 4.0;
                double height = a.Height + 4.0;

                tipRectangle = new Rectangle();
                tipRectangle.Height = height;
                tipRectangle.Width = width;
                tipRectangle.Margin = new Thickness(aThick.Left - 2.0, aThick.Top - 2.0, bThick.Right + a.Width, bThick.Bottom);
                tipRectangle.StrokeThickness = 3.0;
                tipRectangle.StrokeDashArray = new DoubleCollection() { 2.0 };
                tipRectangle.Stroke = Brushes.LightGreen;
                tipRectangle.Opacity = 0.0;

                ButtonPositionCanvas.Children.Add(tipRectangle);


                DoubleAnimationUsingKeyFrames animate = new DoubleAnimationUsingKeyFrames();
                animate.Duration = TimeSpan.FromSeconds(2.0);
                LinearDoubleKeyFrame dkf1 = new LinearDoubleKeyFrame(0.0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(0.0)));
                LinearDoubleKeyFrame dkf2 = new LinearDoubleKeyFrame(1.0, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(1.0)));

                animate.KeyFrames.Add(dkf1);
                animate.KeyFrames.Add(dkf2);

                Storyboard.SetTarget(animate, tipRectangle);
                Storyboard.SetTargetProperty(animate, new PropertyPath(Rectangle.OpacityProperty));

                Storyboard sb = new Storyboard();
                sb.Children.Add(animate);
                sb.Completed += tipRectangleCompleted;
                sb.AutoReverse = true;
                sb.Begin();

            }
        }

        private void tipRectangleCompleted(object sender, EventArgs e)
        {
            ButtonPositionCanvas.Children.Remove(tipRectangle);
        }

        // Interface Methoden

        public void hasCompletedSorting()
        {
            current.solve();
        }

        public void animateSkewingOfButton()
        {
            ToggleButton btn = buttonList[0] as ToggleButton;

            TranslateTransform tT = new TranslateTransform();

            /*Thickness thick = btn.Margin;
            thick.Left += 200;

            ThicknessAnimation thickAnim = new ThicknessAnimation();
            thickAnim.Duration = new Duration(TimeSpan.FromSeconds(2));
            thickAnim.To = thick;

            PowerEase pEase = new PowerEase();
            pEase.EasingMode = EasingMode.EaseInOut;

            thickAnim.EasingFunction = pEase;

            Storyboard.SetTarget(thickAnim, btn);
            Storyboard.SetTargetProperty(thickAnim, new PropertyPath(ToggleButton.MarginProperty));


            Storyboard sb = new Storyboard();
            sb.Children.Add(thickAnim);

            sb.Begin();*/

            Thickness thick = btn.Margin;

            Double val = ButtonPositionCanvas.ActualWidth - thick.Left;

            DoubleAnimation dAnim = new DoubleAnimation();
            dAnim.Duration = new Duration(TimeSpan.FromSeconds(2));
            dAnim.To = val;

            PowerEase pEase = new PowerEase();
            pEase.EasingMode = EasingMode.EaseInOut;
            dAnim.EasingFunction = pEase;

            dAnim.BeginTime = TimeSpan.FromSeconds(0.1);

            tT.BeginAnimation(TranslateTransform.XProperty, dAnim);
            btn.RenderTransform = tT;

            //Storyboard.SetTarget(dAnim, btn);
            //Storyboard.SetTargetProperty(dAnim, new PropertyPath(TranslateTransform.XProperty));

            //Storyboard sb = new Storyboard();
            //sb.Children.Add(dAnim);

            //sb.Begin();

        }

        public void buttonAtCorrectPosition(int index, double animDelay)
        {
            if (index < 0 || index >= buttonList.Count)
                return;


            Duration dur = new Duration(TimeSpan.FromSeconds(1));

            SolidColorBrush selectionColorBrush = (SolidColorBrush)FindResource("SortationDoneBrush");

            ColorAnimation doneSortationAnimation = new ColorAnimation();
            doneSortationAnimation.To = selectionColorBrush.Color;
            doneSortationAnimation.Duration = dur;
            doneSortationAnimation.BeginTime = TimeSpan.FromSeconds(animDelay);

            Storyboard sb = new Storyboard();

            ToggleButton buttonToMarkAsCorrect = null;

            buttonToMarkAsCorrect = (ToggleButton)buttonList[index];

            if (buttonToMarkAsCorrect != null)
            {
                buttonToMarkAsCorrect.IsEnabled = false;
                ColorAnimation tempSortationAnimation = doneSortationAnimation.Clone();
                Storyboard.SetTarget(tempSortationAnimation, buttonToMarkAsCorrect);
                Storyboard.SetTargetProperty(tempSortationAnimation, new PropertyPath("(ToggleButton.Background).(SolidColorBrush.Color)"));

                sb.Children.Add(tempSortationAnimation);
                sb.Begin();
            }
        }
    }
}
